
#ifndef __KEY_DB_H
#define __KEY_DB_H

#include <vector>
#include <apr_pools.h>
#include "../crypt/KeyPair.h"
#include "../crypt/keys.h"
#include "SQLiteDB.h"

// keyname char(64)
// keytype char(32)
// keydata char(4096)

#define OBTAIN_NAMED_KEYPAIR__WRONG_PASSWORD   -1
#define OBTAIN_NAMED_KEYPAIR__NO_ERROR         0
#define OBTAIN_NAMED_KEYPAIR__NO_EXISTING_KEYS 1
#define OBTAIN_NAMED_KEYPAIR__BROKEN_KEYS      2

class KeyDB : public SQLiteDB
{
   public:
      KeyDB(const char *filename, const char *iWIPpassword, const char *iselfkey, const char *ipass, int persists) : SQLiteDB(filename, persists)
      {
         CreateTablesIfNecessary();
         if (iWIPpassword)
         {
            WIPpassword = (char *)malloc(sizeof(char)*(strlen(iWIPpassword)+1));
            strcpy(WIPpassword, iWIPpassword);
         } else
         {
            WIPpassword = NULL;
         }
         if (iselfkey)
         {
            selfkey = (char *)malloc(sizeof(char)*(strlen(iselfkey)+1));
            strcpy(selfkey, iselfkey);
         } else
         {
            selfkey = NULL;
         }
         selfkeypair = NULL;
         if (selfkey) GetMainKeyset(&selfkeypair, selfkey, KEY_BITS, (char *)ipass);
      }
      ~KeyDB()
      {
         if (WIPpassword) free(WIPpassword);
         if (selfkey) free(selfkey);
         if (selfkeypair) delete selfkeypair;
      }
      int AskIsThisOkay(const char *prompt);
      static char *AskPassword(const char *prompt);
      static char *AskPasswordEx(const char *prompt);
      static char *AskPrompt(const char *prompt);
      void CreateTablesIfNecessary();
      std::vector<char *> *GetPrivateKeyStringList(const char *named);
      std::vector<char *> *GetPublicKeyStringList(const char *named);
      KeyPair *ObtainNamedKeyPair(const char *named, const char *passprompt, char **password, int *errorcode);
      KeyPair *ObtainNewNamedKeyPair(const char *named, const char *passprompt, char **password, int nbits);
      void GenerateKeyPairIntoDB(const char *owner, const char *name, const char *password, int nbits);
      void AddPrivateKey(const char *name, KeyPair *keypair, const char *owner);
      void AddPrivateKeyWithPassword(const char *name, const char *password, KeyPair *keypair, const char *owner);
      void AddPublicKey(const char *name, KeyPair *keypair, const char *owner);
      void AddPublicKey(const char *name, const char *keytype, const char *keydata, const char *owner);
      int GetMainKeyset(KeyPair **kp, const char *name, int nobits, char *password);
      int HasOwnKey() { return (selfkeypair != NULL); }
      KeyPair *GetPublicKeyByName(const char *name);
      KeyPair *GetPrivateKeyByName(const char *name);
      KeyPair *GetPrivateKeyByName(const char *name, const char *Apassword);
      KeyPair *GetLatestPublicKeyByOwner(const char *owner);
      KeyPair *GetLatestPrivateKeyByOwner(const char *owner);
      PublicKey *NewGetPublicKeyByName(const char *name);
      /*
      PrivateKey *NewGetPrivateKeyByName(const char *name);
      
      PrivateKey *NewGetPrivateKeyByName(const char *name, const char *Apassword);
      PublicKey *NewGetLatestPublicKeyByOwner(const char *owner);
      PrivateKey *NewGetLatestPrivateKeyByOwner(const char *owner);
      */
      void DeletePublicKeyByName(const char *name);
      void DeletePrivateKeyByName(const char *name);
      int OutputNamedPublicKeyToFile(const char *keyname, const char *filename, apr_pool_t *mp);
      int InputPublicKeyFromFile(const char *filename, const char *keyname, const char *owner, apr_pool_t *mp);
      int InputPrivateKeyFromFile(const char *filename, const char *keyname, const char *owner, apr_pool_t *mp);
      char *GetLatestPublicKeyNameOfOwner(const char *owner);
      char *GetLatestPrivateKeyNameOfOwner(const char *owner);
      int TryToUpdateOwnersKeys(KeyDB *otherkeydb, const char *owner, int keylifetime_secs);
      void RollbackOwnersKeyToPreviousKey(const char *owner, const char *oldkeyname);
      void KeyPairNowUsedByActor(const char *keyuuid);
      void KeyNowUnusedByActor(const char *keyuuid);
      void KeyNowDeletedByActor(const char *keyuuid);
      void MarkKeyPairAsExpendable(const char *keyuuid);
      void MarkKeyPairAsLatest(const char *keyuuid);
      void MarkKeyPairAsOld(const char *keyuuid);
      void MarkKeyPairAsLatestButExpendableWhenZero(const char *keyuuid);
      int EnsureChainBaseAnchored(const char *keyuuid);
      int GetPublicKeyUsedCount(const char *keyuuid);
      int GetPrivateKeyUsedCount(const char *keyuuid);
      int GetPublicKeyExistsCount(const char *keyuuid);
      int GetPrivateKeyExistsCount(const char *keyuuid);
      std::vector<char *> *GetPrivateKeyNamesWithUsedCountAtZeroAndOwner(const char *owner);
      void ReplaceMainKeyPairWithUpdatedVersions(const char *owner);
      void PromoteKeyOfUnauthorised(const char *name);
      int CheckForPublicKeyByName(const char *name);
      char *GetWorkStoreFromComputeKey(const char *name);
      int IsKeyIntendedForCompute(const char *name);
      void ShowKeyStatus();
      void CleanOldKeys();
      char *WIPpassword;
      char *selfkey;
      KeyPair *selfkeypair;
};

#endif
